/**
 * This file is part of Adaptools.
 * 
 * Adaptools is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Adaptools is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 * along with Adaptools.  If not, see http://www.gnu.org/licenses/. 
 */
package org.adaptools.filecontroler.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.adaptools.base.Mechanism;
import org.adaptools.base.Queue;
import org.adaptools.base.exception.AdaptoolsException;
import org.adaptools.filecontroler.AdaptoolsFileController;
import org.adaptools.filecontroler.util.AdaptoolsFileControlerMessages;
import org.adaptools.repository.base.Repository;

/**
 * Class that implements FileControler
 * 
 * @author Denys G. Santos (gsdenys@gmail.com)
 * @since 3.0.0
 */
public class AdaptoolsFileControlerImpl extends AbstractFileControler implements
		AdaptoolsFileController {

	/**
	 * @see org.adaptools.filecontroler.AdaptoolsFileController#init(Repository,
	 *      String)
	 */
	public void init(Repository repository, String mechanismUUID) {
		super.repository = repository;
		super.mechanismUUID = mechanismUUID;
	}

	/**
	 * @see org.adaptools.filecontroler.AdaptoolsFileController#save(String)
	 */
	@Override
	public void save(String filePath) throws AdaptoolsException {
		byte[] buffer = new byte[1024];
		
		try {
			//get the name an name less extension from filePath 
			String[] split = filePath.split("/");
			String name = split[split.length - 1];
			String[] nameSplit = name.split("\\.");
			String singleName = nameSplit[0];
					
			//create a temp Directory
			Path tempFolder = Files.createTempDirectory("ADAPTOOLS-TEMP-" + singleName + "-");
			
			//get mechanism  and repository
			String uuid = super.mechanismUUID;
			Repository repository = super.repository;
			Mechanism mechanism = repository.get(uuid);
			
			//Save Helper
			if(repository.getHelper() != null && !repository.getHelper().trim().equals("")){
				String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.HELPER.getFileSuffix();
				this.saveAs(AdaptoolsFileType.HELPER, fileName);
			}
			
			//saver Semantic Action
		    if(repository.getSemantic() != null && !repository.getSemantic().trim().equals("")){
		    	String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.SEMANTIC_ACTION.getFileSuffix();
				this.saveAs(AdaptoolsFileType.SEMANTIC_ACTION, fileName);
		    }
		    
		    //save output
		    if(mechanism.getOutput() != null && !mechanism.getOutput().toString().equals("")){
		    	String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.OUTPUT.getFileSuffix();
				this.saveAs(AdaptoolsFileType.OUTPUT, fileName);
		    }
			
		    //save input
		    if(mechanism.getQueue() != null && !mechanism.getQueue().toString().equals("")){
		    	String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.INPUT.getFileSuffix();
				this.saveAs(AdaptoolsFileType.INPUT, fileName);
		    }
		    
		    //save tranducer
		    if(mechanism.getTransducer() != null && !mechanism.getTransducer().toString().equals("")){
		    	String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.TRANSDUCER.getFileSuffix();
				this.saveAs(AdaptoolsFileType.TRANSDUCER, fileName);
		    }
		    
		    //save mechenism
		    if(mechanism.getRuleCollection() != null && !mechanism.getRuleCollection().toString().equals("")){
		    	String fileName = tempFolder.toString() + "/" + singleName + AdaptoolsFileType.MACHINE.getFileSuffix();
				this.saveAs(AdaptoolsFileType.MACHINE, fileName);
		    }
		    
		    //Create Zip File
		    FileOutputStream fout = new FileOutputStream(filePath);
		    ZipOutputStream zout = new ZipOutputStream(fout);
		    
		    File folder = new File(tempFolder.toString());
		    File[] listOfFiles = folder.listFiles();
		    
		    for(File file : listOfFiles) {
		        ZipEntry ze = new ZipEntry(file.getName());
		        zout.putNextEntry(ze);
		        
		        FileInputStream in = new FileInputStream(file.getAbsolutePath());
		        
	    		int len;
	    		while ((len = in.read(buffer)) > 0) {
	    			zout.write(buffer, 0, len);
	    		}
	 
	    		in.close();
		    }
		    zout.closeEntry();
		    zout.close();
			
		} catch (IOException e) {
			throw new AdaptoolsException(
					AdaptoolsFileControlerMessages.ERROR_FILE_UNABLE_TO_SAVE_PACKAGE
							.getId());
		}
	}

	/**
	 * @see org.adaptools.filecontroler.AdaptoolsFileController#saveAs(AdaptoolsFileType,
	 *      String)
	 */
	@Override
	public void saveAs(AdaptoolsFileType type, String filePath)
			throws AdaptoolsException {

		if (type.equals(AdaptoolsFileType.PACKAGE)) {
			// save adaptools package
			this.save(filePath);
		} else if (type.equals(AdaptoolsFileType.INPUT)) {
			// save adptools input
			String uuid = super.mechanismUUID;
			Mechanism mechanism = this.repository.get(uuid);
			Queue queue = mechanism.getQueue();
			String str = queue.toString();
			super.saveInput(str, filePath);
		} else if (type.equals(AdaptoolsFileType.MACHINE)) {
			// save adaptools machine
			String uuid = super.mechanismUUID;
			Mechanism mechanism = this.repository.get(uuid);
			super.saveMachine(mechanism, filePath);
		} else if (type.equals(AdaptoolsFileType.SEMANTIC_ACTION)) {
			// save adaptools semantic actions
			String str = this.repository.getSemantic();
			super.saveSemanticAction(str, filePath);
		} else if (type.equals(AdaptoolsFileType.OUTPUT)) {
			// save adaptools output
			String uuid = super.mechanismUUID;
			Mechanism mechanism = this.repository.get(uuid);
			Queue queue = mechanism.getOutput();
			String str = queue.toString();
			super.saveOutput(str, filePath);
		} else if (type.equals(AdaptoolsFileType.TRANSDUCER)) {
			// save adaptools tranducer
			String uuid = super.mechanismUUID;
			Mechanism mechanism = this.repository.get(uuid);
			Queue queue = mechanism.getTransducer();
			String str = queue.toString();
			super.saveTransducer(str, filePath);
		} else if (type.equals(AdaptoolsFileType.HELPER)) {
			// save adaptools helper
			String str = this.repository.getHelper();
			super.saveHelper(str, filePath);
		}
	}

	/**
	 * @see org.adaptools.filecontroler.AdaptoolsFileController#load(java.lang.String)
	 */
	@Override
	public void load(String filePath) throws AdaptoolsException {
		AdaptoolsFileType type = super.getFileType(filePath);
		this.load(type, filePath);
	}

	/**
	 * @see org.adaptools.filecontroler.AdaptoolsFileController#load(org.adaptools.filecontroler.impl.AdaptoolsFileType,
	 *      java.lang.String)
	 */
	@Override
	public void load(AdaptoolsFileType type, String filePath)
			throws AdaptoolsException {

		if (type.equals(AdaptoolsFileType.PACKAGE)) {
			// load adaptools package
			super.loadPackage(filePath);
		} else if (type.equals(AdaptoolsFileType.INPUT)) {
			// load adptools input
			super.loadInput(filePath);
		} else if (type.equals(AdaptoolsFileType.MACHINE)) {
			// load adaptools machine
			super.loadMachine(filePath);
		} else if (type.equals(AdaptoolsFileType.SEMANTIC_ACTION)) {
			// load adaptools semantic actions
			super.loadSemanticAction(filePath);
		} else if (type.equals(AdaptoolsFileType.OUTPUT)) {
			// load adaptools output
			super.loadOutput(filePath);
		} else if (type.equals(AdaptoolsFileType.TRANSDUCER)) {
			// load adaptools tranducer
			super.loadTransducer(filePath);
		} else if (type.equals(AdaptoolsFileType.HELPER)) {
			// load adaptools helper
			super.loadHelper(filePath);
		}
	}

}
